home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3.2 / Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO / packet / n17jsrc / slip.c < prev    next >
C/C++ Source or Header  |  1991-03-07  |  6KB  |  260 lines

  1. /* SLIP (Serial Line IP) encapsulation and control routines.
  2.  * Copyright 1991 Phil Karn
  3.  *
  4.  * Van Jacobsen header compression hooks added by Katie Stevens, UC Davis
  5.  *
  6.  *    - Feb 1991    Bill_Simpson@um.cc.umich.edu
  7.  *            reflect changes to header compression calls
  8.  *            revise status display
  9.  */
  10. #include <stdio.h>
  11. #include "global.h"
  12. #include "config.h"
  13. #include "mbuf.h"
  14. #include "iface.h"
  15. #include "ip.h"
  16. #include "slhc.h"
  17. #include "asy.h"
  18. #include "slip.h"
  19. #include "trace.h"
  20.  
  21. static struct mbuf *slip_decode __ARGS((struct slip *sp,char c));
  22. static struct mbuf *slip_encode __ARGS((struct mbuf *bp));
  23.  
  24. /* Slip level control structure */
  25. struct slip Slip[ASY_MAX];
  26.  
  27. /* Send routine for point-to-point slip */
  28. int
  29. slip_send(bp,iface,gateway,prec,del,tput,rel)
  30. struct mbuf *bp;    /* Buffer to send */
  31. struct iface *iface;    /* Pointer to interface control block */
  32. int32 gateway;        /* Ignored (SLIP is point-to-point) */
  33. int prec;
  34. int del;
  35. int tput;
  36. int rel;
  37. {
  38. #ifdef VJCOMPRESS
  39.     register struct slip *sp;
  40.     int type;
  41. #endif
  42.     if(iface == NULLIF){
  43.         free_p(bp);
  44.         return -1;
  45.     }
  46. #ifdef VJCOMPRESS
  47.     sp = &Slip[iface->xdev];
  48.     if (sp->escaped & SLIP_VJCOMPR) {
  49.         /* Attempt IP/ICP header compression */
  50.         type = slhc_compress(sp->slcomp,&bp,TRUE);
  51.         bp->data[0] |= type;
  52.     }
  53. #endif
  54.     return (*iface->raw)(iface,bp);
  55. }
  56. /* Send a raw slip frame */
  57. int
  58. slip_raw(iface,bp)
  59. struct iface *iface;
  60. struct mbuf *bp;
  61. {
  62.     struct mbuf *bp1;
  63.  
  64.     dump(iface,IF_TRACE_OUT,Slip[iface->xdev].type,bp);
  65.     iface->rawsndcnt++;
  66.     iface->lastsent = secclock();
  67.     if((bp1 = slip_encode(bp)) == NULLBUF){
  68.         free_p(bp);
  69.         return -1;
  70.     }
  71.     if (iface->trace & IF_TRACE_RAW)
  72.         raw_dump(iface,-1,bp1);
  73.     return Slip[iface->xdev].send(iface->dev,bp1);
  74. }
  75. /* Encode a packet in SLIP format */
  76. static
  77. struct mbuf *
  78. slip_encode(bp)
  79. struct mbuf *bp;
  80. {
  81.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  82.     register char *cp;
  83.     int c;
  84.  
  85.     /* Allocate output mbuf that's twice as long as the packet.
  86.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  87.      */
  88.     lbp = alloc_mbuf((int16)(2*len_p(bp) + 2));
  89.     if(lbp == NULLBUF){
  90.         /* No space; drop */
  91.         free_p(bp);
  92.         return NULLBUF;
  93.     }
  94.     cp = lbp->data;
  95.  
  96.     /* Flush out any line garbage */
  97.     *cp++ = FR_END;
  98.  
  99.     /* Copy input to output, escaping special characters */
  100.     while((c = PULLCHAR(&bp)) != -1){
  101.         switch(c){
  102.         case FR_ESC:
  103.             *cp++ = FR_ESC;
  104.             *cp++ = T_FR_ESC;
  105.             break;
  106.         case FR_END:
  107.             *cp++ = FR_ESC;
  108.             *cp++ = T_FR_END;
  109.             break;
  110.         default:
  111.             *cp++ = c;
  112.         }
  113.     }
  114.     *cp++ = FR_END;
  115.     lbp->cnt = cp - lbp->data;
  116.     return lbp;
  117. }
  118. /* Process incoming bytes in SLIP format
  119.  * When a buffer is complete, return it; otherwise NULLBUF
  120.  */
  121. static
  122. struct mbuf *
  123. slip_decode(sp,c)
  124. register struct slip *sp;
  125. char c;        /* Incoming character */
  126. {
  127.     struct mbuf *bp;
  128.  
  129.     switch(uchar(c)){
  130.     case FR_END:
  131.         bp = sp->rbp_head;
  132.         sp->rbp_head = NULLBUF;
  133.         sp->rcnt = 0;
  134.         return bp;    /* Will be NULLBUF if empty frame */
  135.     case FR_ESC:
  136.         sp->escaped |= SLIP_FLAG;
  137.         return NULLBUF;
  138.     }
  139.     if(sp->escaped & SLIP_FLAG){
  140.         /* Translate 2-char escape sequence back to original char */
  141.         sp->escaped &= ~SLIP_FLAG;
  142.         switch(uchar(c)){
  143.         case T_FR_ESC:
  144.             c = FR_ESC;
  145.             break;
  146.         case T_FR_END:
  147.             c = FR_END;
  148.             break;
  149.         default:
  150.             sp->errors++;
  151.             break;
  152.         }
  153.     }
  154.     /* We reach here with a character for the buffer;
  155.      * make sure there's space for it
  156.      */
  157.     if(sp->rbp_head == NULLBUF){
  158.         /* Allocate first mbuf for new packet */
  159.         if((sp->rbp_tail = sp->rbp_head = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  160.             return NULLBUF; /* No memory, drop */
  161.         sp->rcp = sp->rbp_head->data;
  162.     } else if(sp->rbp_tail->cnt == SLIP_ALLOC){
  163.         /* Current mbuf is full; link in another */
  164.         if((sp->rbp_tail->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  165.             /* No memory, drop whole thing */
  166.             free_p(sp->rbp_head);
  167.             sp->rbp_head = NULLBUF;
  168.             sp->rcnt = 0;
  169.             return NULLBUF;
  170.         }
  171.         sp->rbp_tail = sp->rbp_tail->next;
  172.         sp->rcp = sp->rbp_tail->data;
  173.     }
  174.     /* Store the character, increment fragment and total
  175.      * byte counts
  176.      */
  177.     *sp->rcp++ = c;
  178.     sp->rbp_tail->cnt++;
  179.     sp->rcnt++;
  180.     return NULLBUF;
  181. }
  182.  
  183.  
  184. /* Process SLIP line input */
  185. void
  186. asy_rx(xdev,p1,p2)
  187. int xdev;
  188. void *p1;
  189. void *p2;
  190. {
  191.     int c;
  192.     struct mbuf *bp;
  193.     register struct slip *sp;
  194.     int cdev;
  195.  
  196.     sp = &Slip[xdev];
  197.     cdev = sp->iface->dev;
  198.  
  199.     while ( (c = sp->get(cdev)) != -1 ) {
  200.         if((bp = slip_decode(sp,(char)c)) == NULLBUF)
  201.             continue;    /* More to come */
  202.  
  203. #ifdef VJCOMPRESS
  204.         if (sp->iface->trace & IF_TRACE_RAW)
  205.             raw_dump(sp->iface,IF_TRACE_IN,bp);
  206.  
  207.         if (sp->escaped & SLIP_VJCOMPR) {
  208.             if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) {
  209.                 if ( slhc_uncompress(sp->slcomp, &bp) <= 0 ) {
  210.                     free_p(bp);
  211.                     sp->errors++;
  212.                     continue;
  213.                 }
  214.             } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
  215.                 bp->data[0] &= 0x4f;
  216.                 if ( slhc_remember(sp->slcomp, &bp) <= 0 ) {
  217.                     free_p(bp);
  218.                     sp->errors++;
  219.                     continue;
  220.                 }
  221.             }
  222.         }
  223. #endif
  224.         if ( net_route( sp->iface, sp->type, bp ) != 0 ) {
  225.             free_p(bp);
  226.         }
  227.     }
  228.     free_p(bp);
  229. }
  230.  
  231.  
  232. /* Show serial line status */
  233. int
  234. slip_status(iface)
  235. struct iface *iface;
  236. {
  237.     struct slip *sp;
  238.  
  239.     if (iface->xdev > SLIP_MAX)
  240.         /* Must not be a SLIP device */
  241.         return 1;
  242.  
  243.     sp = &Slip[iface->xdev];
  244.     if (sp->iface != iface)
  245.         /* Must not be a SLIP device */
  246.         return 1;
  247.  
  248.     tprintf("  IN:\t%lu pkts\n", iface->rawrecvcnt);
  249. #ifdef VJCOMPRESS
  250.     slhc_i_status(sp->slcomp);
  251. #endif
  252.     tprintf("  OUT:\t%lu pkts\n", iface->rawsndcnt);
  253. #ifdef VJCOMPRESS
  254.     slhc_o_status(sp->slcomp);
  255. #endif
  256.     return 0;
  257. }
  258.  
  259.  
  260.